package com.xinghanlaser.applet.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xinghanlaser.applet.base.auth.entity.UserDO;
import com.xinghanlaser.applet.base.auth.mapper.UserMapper;
import com.xinghanlaser.applet.base.auth.service.IUserService;
import com.xinghanlaser.applet.base.auth.vo.UserDataVO;
import com.xinghanlaser.applet.base.auth.vo.UserDetailVO;
import com.xinghanlaser.applet.base.common.entity.ResponseEntity;
import com.xinghanlaser.applet.base.common.exception.ServiceException;
import com.xinghanlaser.applet.base.common.utils.QueryUtil;
import com.xinghanlaser.applet.base.flow.mapper.FlowLineStepMapper;
import com.xinghanlaser.applet.base.flow.vo.PointVO;
import com.xinghanlaser.applet.base.oss.model.UploadObjectResult;
import com.xinghanlaser.applet.base.oss.service.OssService;
import com.xinghanlaser.applet.entity.*;
import com.xinghanlaser.applet.mapper.DeliveryMapper;
import com.xinghanlaser.applet.mapper.RolePointStateMapper;
import com.xinghanlaser.applet.mapper.TopicDetailMapper;
import com.xinghanlaser.applet.query.TopicQuery;
import com.xinghanlaser.applet.service.*;
import com.xinghanlaser.applet.vo.applet.ProductDetailVO;
import com.xinghanlaser.applet.vo.applet.TopicCountVO;
import com.xinghanlaser.applet.vo.applet.TopicHandleHistoryVO;
import com.xinghanlaser.applet.vo.applet.TopicVO;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * <p>
 *
 * <p>
 *
 * @author: mftuo 陀铭峰
 * @since: 2024/5/8 9:11
 */
@Service
public class TopicServiceImpl implements ITopicService {
    @Resource
    private DeliveryMapper deliveryMapper;

    @Resource
    private ITopicDetailService detailService;

    @Resource
    private ITopicHandleDetailService handleService;

    @Resource
    private ITopicBindService bindService;

    @Resource
    private IUserService userService;

    @Resource
    private TopicDetailMapper topicDetailMapper;

    @Resource
    private OssService ossService;

    @Resource
    private FlowLineStepMapper flowLineStepMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private IPointStateService pointStateService;

    @Resource
    private RolePointStateMapper rolePointStateMapper;

    @Resource
    private IDealerSecretKeyService dealerService;

    @Override
    public ProductDetailVO getProductDetail(String productSn) {
        // 获取当前请求用户信息
        UserDetailVO userDetail = Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
                .map(item -> (String) item.getPrincipal())
                .map(userName -> userService.queryUserDetail(new UserDO().setUserName(userName)))
                .orElseThrow(() -> new ServiceException("获取信息失败"));

        Delivery entity = null;

        // 超级管理员不校验
        if(userDetail.getIsSuperAdmin()){
            entity = deliveryMapper.selectOne(Wrappers.lambdaQuery(new Delivery())
                    .select(
                            Delivery::getSerialno,
                            Delivery::getSpec,
                            Delivery::getCustomername,
                            Delivery::getDeliverytime,
                            Delivery::getStatus
                    )
                    .eq(Delivery::getSerialno, productSn)
                    .orderByDesc(Delivery::getCreatedtime)
                    .last("LIMIT 1")
            );
        }
        else {
            List<Delivery> deliveries = deliveryMapper.selectList(Wrappers.lambdaQuery(new Delivery())
                    .select(
                            Delivery::getSerialno,
                            Delivery::getSpec,
                            Delivery::getCustomername,
                            Delivery::getDeliverytime,
                            Delivery::getStatus
                    )
                    .eq(Delivery::getSerialno, productSn)
            );

            // 查询当前用户绑定的经销商名字
            String dealerName = Optional.ofNullable(
                        dealerService.getOne(Wrappers.lambdaQuery(new DealerSecretKey())
                            .select(DealerSecretKey::getId, DealerSecretKey::getDealerName, DealerSecretKey::getBindUserId)
                            .eq(DealerSecretKey::getBindUserId, userDetail.getId())
                        )
                    )
                    .map(DealerSecretKey::getDealerName)
                    .orElseThrow(() -> new ServiceException("未绑定经销商"));


            if(!deliveries.isEmpty()){
                entity = deliveries.stream()
                        .filter(item -> item.getCustomername().equals(dealerName))
                        .findFirst()
                        .orElseThrow(() -> new ServiceException("没有序列号操作"));
            }
        }

        return Optional.ofNullable(entity)
                .map(item ->
                        ProductDetailVO.builder()
                                .productSn(item.getSerialno())
                                .productSpec(item.getSpec())
                                .customerName(item.getCustomername())
                                .status(item.getStatus())
                                .deliverTime(item.getDeliverytime())
                                .build()
                )
                .orElseThrow(() -> new ServiceException("序号不存在"));
    }

    @Override
    public ResponseEntity<TopicVO> getTopicById(Long id, Long roleId) {
        //TODO 暂时只有维保单
        Integer lineTypeId = 1;

        // 获取信息
        TopicVO result = topicDetailMapper.getTopicVoById(id, roleId, lineTypeId);

        if(result == null) return ResponseEntity.ok(null);

        // 获取下一个节点
        Set<PointVO> nextPointList = flowLineStepMapper.getNextPointList(
                roleId,
                result.getCurrentPointId(),
                lineTypeId
        );
        result.setNextPointList(nextPointList);

        // 获取对于当前角色下的订单状态
        Optional.ofNullable(
            rolePointStateMapper.selectOne(Wrappers.lambdaQuery(new RolePointState())
                .select(RolePointState::getId, RolePointState::getStateId, RolePointState::getStateDesc)
                .eq(RolePointState::getRoleId, roleId)
                .eq(RolePointState::getCurrentPointId, result.getCurrentPointId())
                .last("LIMIT 1")
            )
        ).ifPresent(item -> {
            result.setRolePointState(item.getStateId());
            result.setRolePointStateDesc(item.getStateDesc());
        });

        return ResponseEntity.ok(result);
    }


    @Override
    public ResponseEntity<ResponseEntity.PageResult<TopicVO>> pageByCondition(TopicQuery query) {
        //TODO 暂时只有维保单
        Integer lineTypeId = 1;
        final Long roleId = query.getRoleId();

        // 查询详情信息
        ResponseEntity.PageResult<TopicVO> result = QueryUtil.query(
                query,
                () -> topicDetailMapper.getPageByCondition(query)
        );

        if(result.getRecords().isEmpty()){
            ResponseEntity.PageResult<TopicVO> resultEmpty = new ResponseEntity.PageResult<>();
            return ResponseEntity.ok(resultEmpty);
        }

        // 查询当前角色的所有节点
        Set<PointVO> pointOfRole = flowLineStepMapper.getNextPointList(roleId, null, lineTypeId);

        // 查询当前角色的订单状态
        Map<Long, RolePointState> stateMap = rolePointStateMapper.selectList(Wrappers.lambdaQuery(new RolePointState())
                .select(RolePointState::getId, RolePointState::getCurrentPointId, RolePointState::getStateId, RolePointState::getStateDesc)
                .eq(RolePointState::getRoleId, roleId)
        ).stream().collect(Collectors.toMap(RolePointState::getCurrentPointId, item -> item));

        // 获取历史流程信息
        Set<Long> topicIds = result.getRecords()
                .stream()
                .map(TopicVO::getTopicId)
                .collect(Collectors.toSet());

        Map<Long, List<HistoryDTO>> historyMap = topicDetailMapper.getTopicHistoryDesc(roleId, lineTypeId)
                .stream()
                .filter(item -> topicIds.contains(item.getTopicId()))
                .collect(Collectors.groupingBy(HistoryDTO::getTopicId));

        // 处理节点信息
        List<TopicVO> records = result.getRecords();
        for (TopicVO topicVO : records) {
            final Long currentPointId = topicVO.getCurrentPointId();
            final Long topicId = topicVO.getTopicId();
            // 写入下一个节点
            Optional.ofNullable(pointOfRole)
                    .filter(CollectionUtil::isNotEmpty)
                    .map(pointOfRoleList ->
                        pointOfRole.stream()
                        .filter(item -> item.getPreviousPointId().equals(currentPointId))
                        .collect(Collectors.toSet())
                    )
                    .ifPresent(topicVO::setNextPointList);

            // 写入对于当前角色的订单状态
            if(stateMap.containsKey(currentPointId)){
                RolePointState pointState = stateMap.get(currentPointId);
                topicVO.setRolePointState(pointState.getStateId());
                topicVO.setRolePointStateDesc(pointState.getStateDesc());
            }

            //TODO 写入最新的历史信息
            if(historyMap.containsKey(topicId)){
                List<TopicHandleHistoryVO> history = historyMap.get(topicId).stream()
                        .map(item -> BeanUtil.copyProperties(item, TopicHandleHistoryVO.class))
                        .collect(Collectors.toList());

                topicVO.setFlowHistory(history);
            }
        }

        return ResponseEntity.ok(result);
    }

    @Override
    public ResponseEntity<List<UploadObjectResult>> batchUploadPicture(List<MultipartFile> pictures) {
        List<UploadObjectResult> result = ossService.putObjects(pictures);

        return ResponseEntity.ok(result);

    }

    /**
     * 校验申请带是否存在
     * @param id
     */
    @Override
    public TopicDetail validatedTopicId(Long id){
        return Optional.ofNullable(detailService.getById(id))
                .orElseThrow(() -> new ServiceException("申请单ID不存在"));

    }

    /**
     * 通过申请单ID获取处理流程对象
     * @param topicId
     * @return
     */
    @Override
    public TopicHandleDetail getHandleEntityByTopicId(Long topicId){
        return Optional.ofNullable(
            handleService.getOne(Wrappers.lambdaQuery(new TopicHandleDetail())
                .eq(TopicHandleDetail::getTopicId, topicId)
                .last("LIMIT 1")
            )
        )
        .orElseThrow(() -> new ServiceException("处理流程不存在"));
    }

    @Override
    public ResponseEntity<List<UserDataVO>> getUserListByRoleId(Long roleId) {
        List<UserDataVO> result = userMapper.getUserListByRoleId(roleId);

        return ResponseEntity.ok(result);
    }

    @Override
    public ResponseEntity<List<PointState>> getStateList(Long roleId) {
        List<PointState> result = roleId == null ? pointStateService.list() : rolePointStateMapper.getStateListByRoleId(roleId);

        return ResponseEntity.ok(result);
    }

    @Override
    public ResponseEntity<List<TopicCountVO>> getTopicCountList(Long userId, Long roleId) {
        List<TopicCountVO> result = topicDetailMapper.getTopicCountList(roleId, userId);

        return ResponseEntity.ok(result);
    }
}
